#version 450

//enable #include
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_nonuniform_qualifier : require

#include "PBRCommon.h"


layout (input_attachment_index = 0, binding = 0) uniform subpassInput samplerAlbedo;
layout (input_attachment_index = 1, binding = 1) uniform subpassInput samplerposition;
layout (input_attachment_index = 2, binding = 2) uniform subpassInput samplerNormal;


layout (location = 0) out vec4 outColor;

layout (push_constant) uniform SPointLightPushConstants
{
    vec4 viewPos;

	vec3 position;
    float Radius;

	vec4 color;

    float ShadowBias;
} PointLightPushConstant;

layout (set=1, binding = 0) uniform samplerCube CubeShadowMaps[];

void main() 
{
	// Read G-Buffer values from previous sub pass
	vec3 normal = subpassLoad(samplerNormal).rgb;

    if(normal==vec3(0.0))
    {
        //for unlit meshes
        discard;
    }

	vec3 fragPos = subpassLoad(samplerposition).rgb;
	vec3 albedo = subpassLoad(samplerAlbedo).rgb;
	
    float ao=subpassLoad(samplerAlbedo).a;
	float metallic=subpassLoad(samplerposition).a;
	float roughness=subpassLoad(samplerNormal).a;

    vec3 V=normalize(PointLightPushConstant.viewPos.xyz-fragPos);
	vec3 N=normal;
    //base reflectance
    vec3 F0=vec3(0.04);
    F0=mix(F0,albedo,metallic);

    vec3 Sum=vec3(0.0);

    {
        vec3 LightDirectionFromLight=fragPos-PointLightPushConstant.position.xyz;
        
        vec3 ShadowMapUV=vec3(LightDirectionFromLight.x,-LightDirectionFromLight.y,LightDirectionFromLight.z); //convert Engine right hand coordinate to left coordinate that  texture() used
        
        float LightDistance=length(LightDirectionFromLight);

        if(LightDistance>PointLightPushConstant.Radius)
        {
            discard;
        }


        //贴图中的数值就是物体到光源的距离
        float ShadowMapRawDepth=  texture(CubeShadowMaps[0],ShadowMapUV).r+PointLightPushConstant.ShadowBias; 
        float Shadow=float(LightDistance <= ShadowMapRawDepth);

        if(Shadow<=0)
        {
            discard;
        }


        vec3 NormalizedLightDir=-LightDirectionFromLight / LightDistance;


        vec3 Half=normalize(V+NormalizedLightDir);

        //calculate radiance
        float Distance=length(PointLightPushConstant.position.xyz-fragPos);
        float Attenuation=1.0/(Distance*Distance);
        vec3  radiance=PointLightPushConstant.color.xyz*Attenuation;

        //cook-torrance BRDF
        float NDF=DistributionGGX(N,Half,roughness);
        float G=GeometrySmith(N, V, NormalizedLightDir, roughness);   
        vec3  F=fresnelSchlick(max(dot(Half, V), 0.0), F0);

        vec3 numerator=NDF*G*F;
        float denominator=4.0 * max(dot(N, V), 0.0) * max(dot(N, NormalizedLightDir), 0.0) + 0.0001; // + 0.0001 to prevent divide by zero
        vec3 specular= numerator/denominator;

        vec3 Ks=F;
        vec3 Kd=vec3(1.0)-Ks; 
        Kd*=1.0-metallic;

        float NdotL=max(dot(N,NormalizedLightDir),0.0);
        
        Sum+=(Kd*albedo/PI +specular)* radiance * NdotL * Shadow;
    }

    // HDR tonemapping
    vec3 Color = Sum / (Sum + vec3(1.0));

    outColor=vec4(Color,1.0);

}